import uuid
from collections import deque

from PySide6 import QtCore, QtGui
from PySide6.QtCore import QRectF, Qt, QRect, QPoint, QTimer
from PySide6.QtGui import QUndoStack
from PySide6.QtWidgets import QGraphicsScene, QGraphicsRectItem

from 程序核心代码.图形界面.窗口及画布场景 import ViewerEnum


class 画布场景定义(QGraphicsScene):
    添加图形项信号 = QtCore.Signal(QGraphicsRectItem)
    移除图形项信号 = QtCore.Signal(QGraphicsRectItem)
    def __init__(self, 父对象=None):
        super().__init__(parent=父对象)
        self.唯一标识 = uuid.uuid1()
        self.撤销栈 = QUndoStack()
        self.已移动的图形项 = set()
        self.选择框 = None
        self.起始点 = QPoint()
        self.setItemIndexMethod(QGraphicsScene.BspTreeIndex)
        self._网格模式 = ViewerEnum.GRID_DISPLAY_LINES.value
        self._网格颜色 = ViewerEnum.GRID_COLOR.value
        self._背景颜色 = ViewerEnum.BACKGROUND_COLOR.value
        self.setBackgroundBrush(QtGui.QColor(*self._背景颜色))
        self.待添加图形项队列 = deque()
        self.添加图形项信号.connect(self.延时添加图形项)
        self.移除图形项信号.connect(self.移除图形项)

    def 延时添加图形项(self, 图形项):
        self.待添加图形项队列.append(图形项)
        if not hasattr(self, '定时器') or not self.定时器.isActive():
            self.启动定时器()

    def 启动定时器(self):
        self.定时器 = QTimer(self)
        self.定时器.setSingleShot(True)
        self.定时器.timeout.connect(self.处理待添加图形项)
        self.定时器.start(100)

    def 处理待添加图形项(self):
        while self.待添加图形项队列:
            图形项 = self.待添加图形项队列.popleft()
            self.添加图形项执行(图形项)
    def 移除图形项(self, 图形项):
        self.removeItem(图形项)

    def 添加图形项执行(self, 图形项):
        self.addItem(图形项)

    def mouseReleaseEvent(self, event):
        for item in list(self.已移动的图形项):
            item.保存节点位置()
            self.已移动的图形项.remove(item)
        if event.button() == Qt.LeftButton and self.选择框:
            选择矩形 = self.选择框.geometry()
            self.选择框.hide()
            items_in_rect = self.items(QRectF(选择矩形))
            for item in items_in_rect:
                if isinstance(item, QGraphicsRectItem):
                    item.setSelected(True)
            self.选择框 = None
        super().mouseReleaseEvent(event)

    def mouseMoveEvent(self, event):
        if self.选择框:
            当前点 = event.scenePos().toPoint()
            self.选择框.setGeometry(QRect(self.起始点, 当前点).normalized())
        super().mouseMoveEvent(event)

    def _绘制网格(self, painter, rect, pen, grid_size):
        left = int(rect.left())
        right = int(rect.right())
        top = int(rect.top())
        bottom = int(rect.bottom())
        first_left = left - (left % grid_size)
        first_top = top - (top % grid_size)

        lines = []
        lines.extend([
            QtCore.QLineF(x, top, x, bottom)
            for x in range(first_left, right, grid_size)
        ])
        lines.extend([
            QtCore.QLineF(left, y, right, y)
            for y in range(first_top, bottom, grid_size)]
        )

        painter.setPen(pen)
        painter.drawLines(lines)

    def _绘制点(self, painter, rect, pen, grid_size):
        zoom = self.viewer().get_zoom()
        if zoom < 0:
            grid_size = int(abs(zoom) / 0.3 + 1) * grid_size

        left = int(rect.left())
        right = int(rect.right())
        top = int(rect.top())
        bottom = int(rect.bottom())

        first_left = left - (left % grid_size)
        first_top = top - (top % grid_size)

        pen.setWidth(grid_size / 10)
        painter.setPen(pen)

        [painter.drawPoint(int(x), int(y))
         for x in range(first_left, right, grid_size)
         for y in range(first_top, bottom, grid_size)]

    def drawBackground(self, painter, rect):
        super().drawBackground(painter, rect)

        painter.save()
        painter.setRenderHint(QtGui.QPainter.Antialiasing, False)
        painter.setBrush(self.backgroundBrush())

        if self._网格模式 is ViewerEnum.GRID_DISPLAY_DOTS.value:
            pen = QtGui.QPen(QtGui.QColor(*self._网格颜色), 0.65)
            self._绘制点(painter, rect, pen, ViewerEnum.GRID_SIZE.value)

        elif self._网格模式 is ViewerEnum.GRID_DISPLAY_LINES.value:
            zoom = self.viewer().get_zoom()
            if zoom > -0.5:
                pen = QtGui.QPen(QtGui.QColor(*self._网格颜色), 0.65)
                self._绘制网格(painter, rect, pen, ViewerEnum.GRID_SIZE.value)

            color = QtGui.QColor(*self._背景颜色).darker(200)
            if zoom < -0.0:
                color = color.darker(100 - int(zoom * 110))
            pen = QtGui.QPen(color, 0.65)
            self._绘制网格(painter, rect, pen, ViewerEnum.GRID_SIZE.value * 8)

        painter.restore()

    def viewer(self):
        return self.views()[0] if self.views() else None
    def 检查图形项是否存在(self, 图形项):
        return 图形项 in self.items()
    @property
    def 网格模式(self):
        return self._网格模式

    @网格模式.setter
    def 网格模式(self, mode=None):
        if mode is None:
            mode = ViewerEnum.GRID_DISPLAY_LINES.value
        self._网格模式 = mode

    @property
    def 网格颜色(self):
        return self._网格颜色

    @网格颜色.setter
    def 网格颜色(self, color=(0, 0, 0)):
        self._网格颜色 = color

    @property
    def 背景颜色(self):
        return self._背景颜色

    @背景颜色.setter
    def 背景颜色(self, color=(0, 0, 0)):
        self._背景颜色 = color
        self.setBackgroundBrush(QtGui.QColor(*self._背景颜色))


